package com.learn.english.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.neo4j.driver.*;
import org.neo4j.driver.Record;
import org.neo4j.driver.types.Node;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Component
public class GroupUtil {

    private final Driver neo4jDriver;

    // 用于 JSON 序列化
    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    public GroupUtil(Driver neo4jDriver) {
        this.neo4jDriver = neo4jDriver;
    }

    public Map<String, List<String>> getGroupKey(String prompt) {
        List<String> words = new ArrayList<>();
        List<String> sentences = new ArrayList<>();

        // 1. 提取纯英文单词（考虑大小写、数字和连字符）
        Pattern wordPattern = Pattern.compile("[a-zA-Z]+(?:-[a-zA-Z]+)*");
        Matcher wordMatcher = wordPattern.matcher(prompt);
        while (wordMatcher.find()) {
            String word = wordMatcher.group().toLowerCase(); // 转换为小写以去重
            if (!words.contains(word) && isPureEnglish(word)) { // 简单去重并确保是纯英文
                words.add(word);
            }
        }

        // 2. 提取纯英文句子（以英文标点结尾，且至少含有一个英文字母）
        // 使用更精确的正则表达式来匹配完整的英文句子
        Pattern sentencePattern = Pattern.compile("(?<=^|\\s)([A-Za-z][^.!?]*[.!?])");
        Matcher sentenceMatcher = sentencePattern.matcher(prompt);
        while (sentenceMatcher.find()) {
            String sentence = sentenceMatcher.group().trim();
            if (!sentences.contains(sentence) && isPureEnglish(sentence)) { // 去重并检查是否为纯英文
                sentences.add(sentence);
            }
        }

        Map<String, List<String>> result = new HashMap<>();
        result.put("words", words);
        result.put("sentences", sentences);
        return result;
    }

    /**
     * 判断字符串是否只包含英文字符（允许空格、标点符号）
     */
    private boolean isPureEnglish(String text) {
        for (char c : text.toCharArray()) {
            if (!Character.isWhitespace(c) && !Character.isLetterOrDigit(c) && !isPunctuation(c)) {
                return false; // 非英文字符存在
            }
        }
        return true;
    }

    /**
     * 判断字符是否为英文标点符号
     */
    private boolean isPunctuation(char c) {
        return ",.!?;:'\"()[]{}".indexOf(c) >= 0;
    }

    public String graphRetrieval(Map<String, List<String>> groupKey) {
        List<String> wordKeywords = groupKey.get("words");
        List<String> sentenceKeywords = groupKey.get("sentences");

        List<Map<String, Object>> results = new ArrayList<>();

        try (Session session = neo4jDriver.session()) {

            // 1. 查询单词相关的单词（通过共现于同一个句子）
            for (String word : wordKeywords) {
                String cypherWordToWord = """
                MATCH (w1:word {name: $word})-[:contains]-(:sentence)-[:contains]-(w2:word)
                WHERE w1.name <> w2.name
                RETURN DISTINCT w1 AS source, w2 AS target
                LIMIT 5
            """;
                Result res = session.run(cypherWordToWord, Values.parameters("word", word));
                while (res.hasNext()) {
                    Record record = res.next();
                    Map<String, Object> rel = new HashMap<>();
                    rel.put("source", record.get("source").asNode().asMap());
                    rel.put("target", record.get("target").asNode().asMap());
                    rel.put("type", "word-to-word");
                    results.add(rel);
                }
            }

            // 2. 查询单词相关的句子
            for (String word : wordKeywords) {
                String cypherWordToSentence = """
                MATCH (w:word {name: $word})-[:contains]->(s:sentence)
                RETURN DISTINCT w AS source, s AS target
                LIMIT 5
            """;
                Result res = session.run(cypherWordToSentence, Values.parameters("word", word));
                while (res.hasNext()) {
                    Record record = res.next();
                    Map<String, Object> rel = new HashMap<>();
                    rel.put("source", record.get("source").asNode().asMap());
                    rel.put("target", record.get("target").asNode().asMap());
                    rel.put("type", "word-to-sentence");
                    results.add(rel);
                }
            }

            // 3. 查询句子相关的句子（通过共享单词）
            for (String sentence : sentenceKeywords) {
                String cypherSentenceToSentence = """
                MATCH (s1:sentence {name: $sentence})-[:contains]-(w:word)-[:contains]-(s2:sentence)
                WHERE s1.name <> s2.name
                RETURN DISTINCT s1 AS source, s2 AS target
                LIMIT 5
            """;
                Result res = session.run(cypherSentenceToSentence, Values.parameters("sentence", sentence));
                while (res.hasNext()) {
                    Record record = res.next();
                    Map<String, Object> rel = new HashMap<>();
                    rel.put("source", record.get("source").asNode().asMap());
                    rel.put("target", record.get("target").asNode().asMap());
                    rel.put("type", "sentence-to-sentence");
                    results.add(rel);
                }
            }

            // 4. 查询句子中包含的单词（句子 → 单词）
            for (String sentence : sentenceKeywords) {
                String cypherSentenceToWord = """
                MATCH (s:sentence {name: $sentence})-[:contains]->(w:word)
                RETURN DISTINCT s AS source, w AS target
                LIMIT 5
            """;
                Result res = session.run(cypherSentenceToWord, Values.parameters("sentence", sentence));
                while (res.hasNext()) {
                    Record record = res.next();
                    Map<String, Object> rel = new HashMap<>();
                    rel.put("source", record.get("source").asNode().asMap());
                    rel.put("target", record.get("target").asNode().asMap());
                    rel.put("type", "sentence-to-word");
                    results.add(rel);
                }
            }
            for (String word : wordKeywords) {
                String cypherQuery = """
        MATCH (w:word {name: $word})-[r]-(neighbor:word)
        WHERE neighbor <> w
        RETURN 
          w AS source, 
          neighbor AS target, 
          type(r) AS relationshipType
        LIMIT 50
    """;

                Result res = session.run(cypherQuery, Values.parameters("word", word));
                while (res.hasNext()) {
                    Record record = res.next();

                    // 获取源节点和目标节点
                    Node sourceNode = record.get("source").asNode();
                    Node targetNode = record.get("target").asNode();
                    String relationshipType = record.get("relationshipType").asString();

                    Map<String, Object> rel = new HashMap<>();
                    rel.put("source", sourceNode.asMap());
                    rel.put("target", targetNode.asMap());
                    rel.put("type", relationshipType);  // 使用真实的类型名，比如 related_to、synonym 等
                    results.add(rel);
                }
            }
            return objectMapper.writeValueAsString(results);

        } catch (Exception e) {
            log.error("执行图检索失败", e);
            return null;
        }
    }
}